<template>
	<div class="live-container">
		<el-container>
			<el-main class="main-content">
				<div class="content-wrapper">
					<!-- 左侧直播区域 -->
					<div class="stream-section">
						<div class="video-container">
							<div ref="localVideo" class="video-player">
								<div id="videoContainer" v-show="isStreaming || isCameraOn || isScreenSharing"></div>

								<div class="video-placeholder" v-if="!isStreaming">
									<el-icon size="64">
										<VideoCamera />
									</el-icon>
									<p>准备开播</p>
								</div>
							</div>
							<div class="stream-info" v-if="isStreaming">
								<div class="viewer-count">
									<el-icon>
										<User />
									</el-icon>
									<span>{{ store.viewerCount }}</span>
								</div>
								<div class="stream-duration">
									<el-icon>
										<Timer />
									</el-icon>
									<span>{{ formatDuration }}</span>
								</div>
							</div>
						</div>

						<!-- 控制面板 -->
						<div class="control-panel">
							<div class="stream-settings">
								<!-- <el-input
                  v-model="streamTitle"
                  placeholder="直播标题"
                  :disabled="isStreaming"
                  class="title-input"
                >
                  <template #prefix>
                    <el-icon><Edit /></el-icon>
                  </template>
</el-input> -->
							</div>

							<div class="media-controls">
								<el-tooltip content="麦克风" placement="top" :show-after="500">
									<el-dropdown 
										split-button
										:type="isMicOn ? 'primary' : 'info'" 
										size="large" 
										@click="toggleMic" 
										@command="micDeviceIdChange"
									>
										<span class="btn-wrap">
											<el-icon>
												<Microphone v-if="isMicOn" />
												<Mute v-else />
											</el-icon> 
											<span class="btn-text">{{
												isMicOn ? "静音" : "解除静音"
											}}</span>
										</span>
										<template #dropdown>
											<el-dropdown-menu>
												<el-dropdown-item 
													v-for="(item, index) in micList" 
													:key="index" 
													:command="item.deviceId"
													:class="{'selected':micDeviceId==item.deviceId}"
												>{{ item.label }}</el-dropdown-item>
											</el-dropdown-menu>
										</template>
									</el-dropdown>
								</el-tooltip>

								<el-tooltip content="摄像头" placement="top" :show-after="500">
									<el-dropdown 
										split-button
										:type="isCameraOn ? 'primary' : 'info'" 
										size="large" 
										@click="toggleCamera" 
										@command="cameraDeviceIdChange"
									>
										<span class="btn-wrap">
											<el-icon>
												<VideoCamera />
											</el-icon>
											<span class="btn-text">{{
												isCameraOn ? "停止视频" : "开启视频"
											}}</span>
										</span>
										<template #dropdown>
											<el-dropdown-menu>
												<el-dropdown-item 
													v-for="(item, index) in cameraList" 
													:key="index" 
													:command="item.deviceId"
													:class="{'selected':cameraDeviceId==item.deviceId}"
												>{{ item.label }}</el-dropdown-item>
											</el-dropdown-menu>
										</template>
									</el-dropdown>
								</el-tooltip>

								<el-tooltip content="共享屏幕" placement="top" :show-after="500">
									<el-button :type="isScreenSharing ? 'primary' : 'info'" size="large"
										class="control-btn" @click="toggleScreenShare">
										<el-icon size="20">
											<Monitor />
										</el-icon>
										<span class="btn-text">{{
											isScreenSharing ? "结束共享" : "共享屏幕"
										}}</span>
									</el-button>
								</el-tooltip>

								<el-tooltip :content="isStreaming ? '结束直播' : '开始直播'" placement="top">
									<el-button :type="isStreaming ? 'danger' : 'success'" size="large"
										@click="toggleStream" class="stream-button">
										<el-icon class="button-icon" size="20">
											<VideoPlay />
										</el-icon>
										{{ isStreaming ? "结束直播" : "开始直播" }}
									</el-button>
								</el-tooltip>
							</div>
						</div>
					</div>

					<!-- 右侧聊天区域 -->
					<div class="chat-section">
						<div class="chat-header">
							<div class="header-title">
								<el-icon>
									<ChatLineRound />
								</el-icon>
								<span>直播间消息</span>
								<el-tag size="small" type="info" class="message-count">
									<el-icon>
										<User />
									</el-icon>{{ store.viewerCount }}
								</el-tag>
							</div>
						</div>

						<div class="chat-messages custom-scrollbar" ref="messageContainer">
							<div class="messages-wrapper">
								<div v-if="messages.length === 0" class="empty-state">
									<el-empty description="暂无消息" :image-size="120">
										<template #image>
											<el-icon size="60" class="empty-icon">
												<ChatDotRound />
											</el-icon>
										</template>
									</el-empty>
								</div>
								<virtual-list v-else class="list-virtual" :data-key="'id'" :data-sources="messages"
									:data-component="messageComponent" :estimate-size="70" :keeps="30" />
							</div>
						</div>

						<!-- 发送消息输入框 -->
						<message-input @send="sendMessage"></message-input>
						
					</div>
				</div>
			</el-main>
		</el-container>
	</div>
</template>

<script setup>
import {
	ref,
	onMounted,
	onBeforeUnmount,
	computed,
	watch,
	nextTick,
} from "vue";
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
import {
	VideoCamera,
	Microphone,
	Mute,
	Monitor,
	VideoPlay,
	ChatLineRound,
	InfoFilled,
	User,
	Timer,
	Edit,
	ChatDotRound,
} from "@element-plus/icons-vue";
import dayjs from "dayjs";
import VirtualList from "vue3-virtual-scroll-list";
import MessageInput from "./components/MessageInput.vue";
import { defineComponent, h } from "vue";
import { createSocket } from "@/utils/socket";
import { AliRTSPusher } from "aliyun-rts-pusher";
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()


// 状态管理
const localVideo = ref(null);
const isStreaming = ref(false);
const isMicOn = ref(false);
const isCameraOn = ref(false);
const isScreenSharing = ref(false);
const streamTitle = ref("");
const streamStartTime = ref(null);
const durationTimer = ref(null);
const messageContainer = ref(null);

// 消息列表
const messages = ref([]);

// 生命周期钩子
onMounted(async () => {
	initSDK()
	initWebSocket();
	socket.connect();

	// 添加点击事件监听器
	document.addEventListener("click", handleClickOutside);
});

// 初始化 SDK
let pushClient;
// 摄像头列表
const cameraList = ref([])
// 麦克风列表
const micList = ref([])
const initSDK = async () => {
	navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
        console.log("麦克风权限已获取");
    })
    .catch(error => {
        console.error("无法获取麦克风权限:", error);
        ElMessage.error("请允许麦克风权限以启用声音");
    });


	// 创建推流实例
	pushClient = AliRTSPusher.createClient();
	// 监听错误事件
	pushClient.on("error", (err) => {
		// console.log(err.errorCode);
    switch (err.errorCode) {
		case 10001:
			ElMessage.warning("没有找到音频设备");
			break;
		case 10002:
			ElMessage.warning("没有找到视频设备");
			break;
		case 10003:
			ElMessage.warning("不允许使用音频设备");
			break;
		case 10004:
			ElMessage.warning("不允许使用视频设备");
			break;
		case 10005:
			ElMessage.warning("没有使用音频设备权限");
			break;
		case 10006:
			ElMessage.warning("没有使用视频设备权限");
			break;
		case 10007:
			ElMessage.warning("音频设备被终止，如拔出麦克风或者浏览器授权被取消");
			break;
		case 10008:
			ElMessage.warning("视频设备被终止，如拔出摄像头或者浏览器授权被取消。");
			break;
		case 10010:
			ElMessage.warning("屏幕共享未知错误");
			break;
		case 10011:
			ElMessage.warning("屏幕共享弹窗被用户拒绝");
			break;
		case 10012:
			isScreenSharing.value = false;
			ElMessage.warning("屏幕共享结束");
			break;
		case 10013:
			ElMessage.warning("浏览器被系统禁止屏幕共享权限");
			break;
		case 10018:
			ElMessage.warning("浏览器不支持屏幕共享");
			break;
		case 10020:
			ElMessage.warning("传入的自定义流无效");
			break;
		case 10300:
			ElMessage.warning("	推流URL错误");
			break;
		case 10301:
			ElMessage.warning("推流缺少音频");
			break;
    }
	});

	const videoEl = pushClient.setRenderView("videoContainer");
	// 如果希望将本地预览静音（推出去的流不会静音）
	videoEl.muted = true;
	// 设置视频质量。
	pushClient.setVideoQuality('720p_1');
	
	// 获取设备列表
	const deviceManager = await pushClient.getDeviceManager();
	// 获取摄像头列表
	cameraList.value = await deviceManager.getCameraList();
	// 获取麦克风列表
	micList.value = await deviceManager.getMicList();
	
	// 初始化时尝试打开麦克风
	try {
		const micStreamId = await pushClient.startMicrophone();
		isMicOn.value = true;
		console.log("麦克风已开启");

		// 获取音频效果管理器
		// const audioEffectManager = pushClient.getAudioEffectManager();
		// // 设置麦克风音量
		// audioEffectManager.setVolume(50, micStreamId);
		
	} catch (error) {
		console.error("初始化麦克风失败:", error);
		ElMessage.warning("麦克风初始化失败，请检查麦克风权限");
	}

	// 确保音频推流已启用
	pushClient.enableAudio(true);
	console.log("音频推流已启用");
};

// 音量监测相关变量
const audioLevel = ref(0);
const isAudioDetected = ref(false);
const volumeMonitorTimer = ref(null);


// 停止音量监测
const stopVolumeMonitor = () => {
	if (volumeMonitorTimer.value) {
		clearInterval(volumeMonitorTimer.value);
		volumeMonitorTimer.value = null;
	}
	// 移除音量变化事件监听
	pushClient.off('audioVolumeChange');
};

// 推流时音频检测
const audioDetectedDuringStream = ref(false);

// 选择麦克风
const micDeviceId = ref("default");
const micDeviceIdChange = async (val) => {
	// 关闭麦克风
	try {
		await pushClient.stopMicrophone();
		micDeviceId.value = val;
		// 重新打开麦克风
		await pushClient.startMicrophone(val);
		isMicOn.value = true;
	} catch (error) {
		console.error("麦克风切换失败:", error);
		ElMessage.error("麦克风选择失败");
	}
}

// 选择摄像头
const cameraDeviceId = ref("default");

const cameraDeviceIdChange = async (val) => {
	// 关闭摄像头
	await pushClient.stopCamera(cameraDeviceId.value);
	cameraDeviceId.value = val;
	try {
		await pushClient.startCamera(val);
		isCameraOn.value = true;
	} catch (error) {
		ElMessage.error("摄像头选择失败");
	}
}



// 直播时长
const formatDuration = ref("00:00:00");
// 计算直播时长
const calculateLiveBroadcastDuration = () => {
	if (!streamStartTime.value) return "00:00:00";
	const duration = dayjs().diff(streamStartTime.value, "second");
	const hours = Math.floor(duration / 3600);
	const minutes = Math.floor((duration % 3600) / 60);
	const seconds = duration % 60;
	formatDuration.value = `${hours.toString().padStart(2, "0")}:${minutes
		.toString()
		.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
};

// 添加新的响应式变量
const shouldAutoScroll = ref(true);

// 添加消息限制常量
const MAX_MESSAGES = 200; // 最大消息数量
const BATCH_SIZE = 50; // 每次清理的消息数量

// 监听消息列表变化
watch(
	() => messages.value.length,
	() => {
		nextTick(() => {
			scrollToBottom();
		});
	}
);

// 优化滚动函数
const scrollToBottom = (force = false) => {
	nextTick(() => {
		const container =
			messageContainer.value?.querySelector(".messages-wrapper");
		if (!container) return;

		const isNearBottom =
			container.scrollHeight - container.scrollTop - container.clientHeight <
			150;

		if (force || isNearBottom) {
			container.scrollTo({
				top: container.scrollHeight,
				behavior: force ? "auto" : "smooth",
			});
		}
	});
};

// 修改添加消息的函数
const addMessage = (message) => {
	const newMessage = {
		id: Date.now(),
		...message,
		time: new Date(),
	};


	messages.value.push(newMessage);

	// 当消息超过最大数量时，批量删除旧消息
	if (messages.value.length > MAX_MESSAGES) {
		messages.value = messages.value.slice(-MAX_MESSAGES + BATCH_SIZE);
	}

	// 强制滚动到底部
	scrollToBottom(true);
};

// 获取url参数
const getUrlParameter = (name)=> {
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
    const results = regex.exec(rtsConifg.imUrl);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}

// 创建WebSocket实例
const socket = createSocket({
	url: rtsConifg.imUrl,
	reconnectInterval: 3000,
	heartbeatInterval: 30000,
	maxReconnectAttempts: 30,
	uid: getUrlParameter('uid'),
	live_id: getUrlParameter('live_id'),
	token: getUrlParameter('token'),
});


// 用户信息
const userInfo = ref({});

// WebSocket事件处理
const initWebSocket = () => {
	// 连接成功
	socket.on("connect", () => {
		// addSystemMessage("WebSocket连接成功");
		socket.send({
			type: 'login'
		})
	});

	// 连接关闭
	socket.on("close", () => {
		// addSystemMessage("WebSocket连接断开");
	});

	// 错误处理
	socket.on("error", (error) => {
		// addSystemMessage("WebSocket连接错误");
		console.error("WebSocket错误:", error);
	});

	// 接收消息
	socket.on("message", (data) => {

		if(data.nickname){
			userInfo.value = data;
		}

		if(data.uid === getUrlParameter('uid')){
			return
		}

		if (data.type === "chat") {
			addMessage({
				type: "user",
				content: data.msg,
				nickname: data.nickname,
				avatar:
					data.avatar ||
					"https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
			});
		}else if(data.type == 'come_in' || data.type == 'open'){
			addMessage({
				type: "system",
				content: data.msg
			});
		}
		
	});
};


// 优化系统消息的处理
const addSystemMessage = (content) => {
	addMessage({
		type: "system",
		content: content.trim(),
	});
};

// 开始/结束直播
const streamLoading = ref(false);
const toggleStream = async () => {
	try {
		if (!isStreaming.value) {
			streamLoading.value = true;
			await startStream();
      		isStreaming.value = true;
			streamStartTime.value = dayjs();
			durationTimer.value = setInterval(() => {
				calculateLiveBroadcastDuration();
			}, 1000);
		} else {
			await stopStream();
		}

	} catch (error) {
		ElMessage.error(`操作失败: ${error.message}`);
	}
};

// 开始直播
const startStream = async () => {
	return new Promise(async (resolve, reject) => {
		try {
			// 确保音频推流已启用
			pushClient.enableAudio(true);
			console.log("音频推流已启用");

			// 确保麦克风已开启
			if (!isMicOn.value) {
				await pushClient.startMicrophone();
				isMicOn.value = true;
				console.log("麦克风已成功开启");
			}

			// 开始推流
			await pushClient.startPush(rtsConifg.pushUrl);
			console.log("推流已开始");

			// 设置麦克风音量为最大
			const audioEffectManager = pushClient.getAudioEffectManager();
			if (audioEffectManager) {
				audioEffectManager.setVolume(100);
				console.log("麦克风音量已设置为最大");
			}

			// 监听推流状态
			pushClient.on("connectStatusChange", (event) => {
				switch (event.status) {
					case 1:
						console.log("推流连接中");
						break;
					case 2:
						console.log("推流已连接");
						streamLoading.value = false;
						resolve();
						break;
					case 3:
						console.warn("推流自动重连中");
						ElMessage.warning("推流自动重连中");
						reject(new Error("推流自动重连中"));
						break;
					case 0:
						console.error("推流中断");
						ElMessage.error("推流中断，请重新开始直播");
						streamLoading.value = false;
						pushClient.stopPush();
						isScreenSharing.value = false;
						isStreaming.value = false;
						reject(new Error("推流中断"));
						break;
				}
			});
		} catch (error) {
			console.error("推流失败:", error);
			ElMessage.error(`推流失败: ${error.message}`);
			reject(error);
		}
	});
};

// 结束直播
const stopStream = async () => {
	ElMessageBox.confirm("确定要结束直播吗？", "提示", {
		confirmButtonText: "确定",
		cancelButtonText: "取消",
		type: "warning",
	})
	.then(() => {
		pushClient.stopPush();
		isScreenSharing.value = false;
    	isStreaming.value = false;
		isCameraOn.value = false;

		streamStartTime.value = null;
		if (durationTimer.value) {
			clearInterval(durationTimer.value);
			durationTimer.value = null;
		}
		formatDuration.value = "00:00:00";
		addSystemMessage("直播结束了");
		handleLiveEnd();
	})
	.catch(() => {
		// 用户取消操作
	});
	
};

// 切换麦克风
const toggleMic = async () => {
	if(isMicOn.value){
		// 关闭麦克风
		try {
			await pushClient.stopMicrophone();
			micDeviceId.value = "default";
			isMicOn.value = false;
			isAudioDetected.value = false;
			audioDetectedDuringStream.value = false; // 重置音频检测状态
		} catch (error) {
			console.error("关闭麦克风失败:", error);
		}
	}else{
		// 打开麦克风
		try {
			await pushClient.startMicrophone(micDeviceId.value);
			isMicOn.value = true;
		} catch (error) {
			console.error("打开麦克风失败:", error);
			ElMessage.error(`麦克风打开失败,请检查麦克风权限`);
		}
	}
};

// 切换摄像头
const cameraLoading = ref(false);
const toggleCamera = async () => {
	cameraLoading.value = true;
	if (isCameraOn.value) {
		// 关闭摄像头
		closeCamera();
	}else {
		if(isScreenSharing.value){
			await pushClient.stopScreenCapture();
			isScreenSharing.value = false;
		}
		// 打开摄像头
		try {
			await pushClient.startCamera();
			isCameraOn.value = true;
		} catch (error) {
			ElMessage.error(`摄像头打开失败,请检查摄像头权限`);
		}
	}
	cameraLoading.value = false;
};

// 切换屏幕共享
const toggleScreenShare = async () => {
	if(isScreenSharing.value){
		await pushClient.stopScreenCapture();
    	isScreenSharing.value = false;
	}else{
		// 关闭摄像头
		closeCamera();
		// 开启屏幕共享并在选择弹窗中优先选择整个屏幕
		const streamId = await pushClient.startScreenCapture({
			audio: true,
			video: { displaySurface: "monitor" },
		});
    	isScreenSharing.value = true;
	}
};


// 关闭摄像头
const closeCamera = async () => {
	if (isCameraOn.value) {
		await pushClient.stopCamera()
		cameraDeviceId.value = "default";
		isCameraOn.value = false;
	}
};

// 格式化时间
const formatTime = (time) => {
	return dayjs(time).format("HH:mm:ss");
};

// 将滚动监听函数提取出来
const handleScroll = () => {
	const messageWrapper =
		messageContainer.value?.querySelector(".messages-wrapper");
	if (messageWrapper) {
		const isNearBottom =
			messageWrapper.scrollHeight -
			messageWrapper.scrollTop -
			messageWrapper.clientHeight <
			150;
		shouldAutoScroll.value = isNearBottom;
	}
};

// 修改消息组件的定义
const messageComponent = defineComponent({
	props: {
		source: {
			type: Object,
			required: true,
		},
	},
	setup(props) {
		return () => {
			if (props.source.type === "system") {
				return h("div", { class: "message-item system" }, [
					h("div", { class: "system-message" }, [
						h("el-icon", null, [h(InfoFilled)]),
						h("span", null, props.source.content),
					]),
				]);
			}

			return h(
				"div",
				{
					class: `message-item user ${props.source.self ? "self" : ""}`,
				},
				[
					h("img", {
						class: `avatar`,
						src: props.source.avatar,
						alt: props.source.nickname,
					}),
					h("div", { class: `message-content ${props.source.self ? "self" : ""}` }, [
						h("div", { class: "message-info" }, [
							h("span", { class: "username" }, props.source.nickname),
							// 如果自己发的显示 我
							props.source.self ? h("span", { class: "my" }, "我") : "",
							h("span", { class: "time" }, formatTime(props.source.time)),
						]),
						h("div", { class: "message-text" }, props.source.content),
					]),
				]
			);
		};
	},
});


// 添加点击事件监听器
const handleClickOutside = (event) => {
	const emojiPicker = document.querySelector(".emoji-picker");
	const emojiButton = document.querySelector(
		".el-input-group__prepend .el-button"
	);

	if (
		emojiPicker &&
		!emojiPicker.contains(event.target) &&
		!emojiButton.contains(event.target)
	) {
		isEmojiPickerVisible.value = false;
	}
};

// 发送消息
const sendMessage = (messageData) => {
	// 发送消息到WebSocket服务器
	if (socket.send(messageData)) {
		addMessage({
			type: "user",
			self: true,
			content: messageData.msg,
			nickname: userInfo.value.nickname,
			avatar: userInfo.value.avatar,
		});
	}
}

const handleLiveEnd = () => {
  try {
    window.close()
  } catch (e) {
	ElMessageBox.confirm("直播已结束,请关闭页面!", "提示", {
		confirmButtonText: "确定",
		cancelButtonText: "取消",
		type: "warning",
	})
	.then(() => {
		window.close()
	})
	.catch(() => {
		console.log('直播已结束,请关闭页面')
	})
  }
}

onBeforeUnmount(() => {
	// 清理直播相关资源
	if (isStreaming.value) {
		stopStream();
	}

	// 清理滚动监听
	const messageWrapper =
		messageContainer.value?.querySelector(".messages-wrapper");
	if (messageWrapper) {
		messageWrapper.removeEventListener("scroll", handleScroll);
	}

	// 清理 WebSocket 相关资源
	if (socket) {
		// 移除所有事件监听
		socket.off("connect");
		socket.off("close");
		socket.off("error");
		socket.off("message");

		// 关闭连接
		socket.close();
	}

	// 清理消息列表
	messages.value = [];

	// 移除点击事件监听器
	document.removeEventListener("click", handleClickOutside);

	// 停止推流
	pushClient.stopPush();
});
</script>

<style lang="less" scoped>
@import url('@/assets/style.less');

:deep(.selected) {
	background-color: var(--el-dropdown-menuItem-hover-fill);
    color: var(--el-dropdown-menuItem-hover-color);
}

.volume-indicator {
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 100%;
  height: 3px;
  background-color: rgba(0, 0, 0, 0.1);
  border-radius: 1px;
  overflow: hidden;
}

.volume-bar {
  height: 100%;
  background-color: #67c23a;
  transition: width 0.2s ease;
  
  &.active {
    background-color: #67c23a;
  }
  
  &:not(.active) {
    background-color: #909399;
  }
}

:deep(.my) {
	display: inline-block;
	padding: 0 4px;
	margin: 0 4px;
	font-size: 12px;
	color: #fff;
	background-color: #409eff;
	border-radius: 2px;
}

</style>
